package org.tpc.printtolls.service;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.io.RandomAccessReadBuffer;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.printing.PDFPrintable;
import org.apache.pdfbox.printing.Scaling;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tpc.printtolls.model.PrintRequest;
import org.tpc.printtolls.model.PrintResult;

import javax.print.*;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.*;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterJob;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 核心打印服务类
 */
public class PrintService {
    
    private static final Logger logger = LoggerFactory.getLogger(PrintService.class);
    private final OkHttpClient httpClient;
    
    public PrintService() {
        this.httpClient = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .build();
    }
    
    /**
     * 执行打印任务
     */
    public PrintResult print(PrintRequest request) {
        logger.info("开始执行打印任务: {}", request);
        
        try {
            // 1. 验证参数
            if (!validateRequest(request)) {
                return PrintResult.failure("打印参数验证失败");
            }
            
            // 2. 下载PDF文件
            byte[] pdfData = downloadPdf(request.getPdfUrl());
            if (pdfData == null) {
                return PrintResult.failure("下载PDF文件失败");
            }
            
            // 3. 加载PDF文档
            PDDocument document = Loader.loadPDF(new RandomAccessReadBuffer(pdfData));
            int pageCount = document.getNumberOfPages();
            
            // 4. 查找打印机
            javax.print.PrintService printerService = findPrinter(request.getPrinterName());
            if (printerService == null) {
                document.close();
                return PrintResult.failure("找不到指定的打印机: " + request.getPrinterName());
            }
            
            // 5. 配置打印参数
            PrintRequestAttributeSet attributes = createPrintAttributes(request);
            
            // 6. 执行打印
            String jobId = executePrint(document, printerService, attributes, request);
            
            document.close();
            
            logger.info("打印任务完成，JobID: {}", jobId);
            return PrintResult.success(jobId, pageCount, request.getCopies());
            
        } catch (Exception e) {
            logger.error("打印过程中发生错误", e);
            return PrintResult.failure("打印失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取可用的打印机列表
     */
    public List<String> getAvailablePrinters() {
        javax.print.PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
        return java.util.Arrays.stream(printServices)
                .map(service -> service.getName())
                .toList();
    }
    
    /**
     * 验证打印请求参数
     */
    private boolean validateRequest(PrintRequest request) {
        if (request == null) {
            logger.warn("打印请求为空");
            return false;
        }
        
        if (request.getPrinterName() == null || request.getPrinterName().trim().isEmpty()) {
            logger.warn("打印机名称为空");
            return false;
        }
        
        if (request.getPdfUrl() == null || request.getPdfUrl().trim().isEmpty()) {
            logger.warn("PDF URL为空");
            return false;
        }
        
        if (request.getCopies() <= 0) {
            logger.warn("打印份数必须大于0");
            return false;
        }
        
        if (request.getPaperWidth() <= 0 || request.getPaperHeight() <= 0) {
            logger.warn("纸张尺寸必须大于0");
            return false;
        }
        
        return true;
    }
    
    /**
     * 下载PDF文件
     */
    private byte[] downloadPdf(String url) {
        try {
            Request request = new Request.Builder()
                    .url(url)
                    .build();
            
            try (Response response = httpClient.newCall(request).execute()) {
                if (!response.isSuccessful()) {
                    logger.error("下载PDF失败，HTTP状态码: {}", response.code());
                    return null;
                }
                
                return response.body().bytes();
            }
        } catch (IOException e) {
            logger.error("下载PDF文件时发生异常", e);
            return null;
        }
    }
    
    /**
     * 查找指定名称的打印机
     */
    private javax.print.PrintService findPrinter(String printerName) {
        javax.print.PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
        
        for (javax.print.PrintService service : printServices) {
            if (service.getName().equals(printerName)) {
                return service;
            }
        }
        
        logger.warn("找不到打印机: {}", printerName);
        return null;
    }
    
    /**
     * 创建打印属性
     */
    private PrintRequestAttributeSet createPrintAttributes(PrintRequest request) {
        PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
        
        // 设置打印份数
        attributes.add(new Copies(request.getCopies()));
        
        // 设置打印质量
        switch (request.getQuality()) {
            case 1 -> attributes.add(PrintQuality.DRAFT);
            case 2 -> attributes.add(PrintQuality.NORMAL);
            case 3, 4 -> attributes.add(PrintQuality.HIGH);
        }
        
        // 设置双面打印
        if (request.isDuplex()) {
            attributes.add(Sides.DUPLEX);
        } else {
            attributes.add(Sides.ONE_SIDED);
        }
        
        // 设置纸张尺寸（如果能匹配标准尺寸则使用标准尺寸，否则在executePrint中通过PageFormat设置）
        MediaSizeName mediaSizeName = findStandardMediaSizeName(request.getPaperWidth(), request.getPaperHeight());
        if (mediaSizeName != null) {
            attributes.add(mediaSizeName);
            logger.debug("使用标准纸张尺寸: {} ({}x{}mm)", mediaSizeName, request.getPaperWidth(), request.getPaperHeight());
        } else {
            // 对于自定义尺寸，我们依赖 PageFormat 设置，这里不添加 MediaSize 属性
            logger.info("将使用自定义纸张尺寸: {}x{}mm", request.getPaperWidth(), request.getPaperHeight());
        }
        
        return attributes;
    }
    
    /**
     * 查找匹配的标准纸张尺寸名称
     * 
     * @param widthMM 宽度（毫米）
     * @param heightMM 高度（毫米）
     * @return 匹配的标准 MediaSizeName，如果没有找到则返回 null
     */
    private MediaSizeName findStandardMediaSizeName(double widthMM, double heightMM) {
        // 允许的误差范围（毫米）
        final double TOLERANCE = 2.0;
        
        // 定义常见的标准纸张尺寸及其对应的 MediaSizeName
        PaperSizeMapping[] paperSizes = {
            // ISO A 系列
            new PaperSizeMapping(210, 297, MediaSizeName.ISO_A4),
            new PaperSizeMapping(297, 420, MediaSizeName.ISO_A3),
            new PaperSizeMapping(148, 210, MediaSizeName.ISO_A5),
            new PaperSizeMapping(105, 148, MediaSizeName.ISO_A6),
            new PaperSizeMapping(74, 105, MediaSizeName.ISO_A7),
            new PaperSizeMapping(52, 74, MediaSizeName.ISO_A8),
            new PaperSizeMapping(37, 52, MediaSizeName.ISO_A9),
            new PaperSizeMapping(26, 37, MediaSizeName.ISO_A10),
            
            // ISO B 系列
            new PaperSizeMapping(250, 353, MediaSizeName.ISO_B4),
            new PaperSizeMapping(176, 250, MediaSizeName.ISO_B5),
            new PaperSizeMapping(125, 176, MediaSizeName.ISO_B6),
            new PaperSizeMapping(88, 125, MediaSizeName.ISO_B7),
            new PaperSizeMapping(62, 88, MediaSizeName.ISO_B8),
            new PaperSizeMapping(44, 62, MediaSizeName.ISO_B9),
            new PaperSizeMapping(31, 44, MediaSizeName.ISO_B10),
            
            // 北美标准
            new PaperSizeMapping(215.9, 279.4, MediaSizeName.NA_LETTER),
            new PaperSizeMapping(215.9, 355.6, MediaSizeName.NA_LEGAL),
            new PaperSizeMapping(184.2, 266.7, MediaSizeName.EXECUTIVE),
            new PaperSizeMapping(279.4, 431.8, MediaSizeName.LEDGER),
            
            // JIS B 系列（日本标准）
            new PaperSizeMapping(182, 257, MediaSizeName.JIS_B5),
            new PaperSizeMapping(128, 182, MediaSizeName.JIS_B6),
            new PaperSizeMapping(91, 128, MediaSizeName.JIS_B7),
            new PaperSizeMapping(64, 91, MediaSizeName.JIS_B8),
            new PaperSizeMapping(45, 64, MediaSizeName.JIS_B9),
            new PaperSizeMapping(32, 45, MediaSizeName.JIS_B10),
        };
        
        for (PaperSizeMapping mapping : paperSizes) {
            // 检查是否匹配（考虑横向和纵向）
            if ((Math.abs(widthMM - mapping.width) <= TOLERANCE && 
                 Math.abs(heightMM - mapping.height) <= TOLERANCE) ||
                (Math.abs(widthMM - mapping.height) <= TOLERANCE && 
                 Math.abs(heightMM - mapping.width) <= TOLERANCE)) {
                
                logger.debug("找到匹配的标准纸张: {} (标准: {}x{}mm, 请求: {}x{}mm)",
                           mapping.mediaSizeName, mapping.width, mapping.height, widthMM, heightMM);
                return mapping.mediaSizeName;
            }
        }
        
        return null;
    }
    
    /**
     * 纸张尺寸映射类
     */
    private static class PaperSizeMapping {
        final double width;
        final double height;
        final MediaSizeName mediaSizeName;
        
        PaperSizeMapping(double width, double height, MediaSizeName mediaSizeName) {
            this.width = width;
            this.height = height;
            this.mediaSizeName = mediaSizeName;
        }
    }
    
    /**
     * 执行打印
     */
    private String executePrint(PDDocument document, javax.print.PrintService printerService, 
                               PrintRequestAttributeSet attributes, PrintRequest request) throws Exception {
        
        PrinterJob printerJob = PrinterJob.getPrinterJob();
        printerJob.setPrintService(printerService);
        
        // 设置页面格式
        PageFormat pageFormat = printerJob.defaultPage();
        Paper paper = pageFormat.getPaper();
        
        // 转换毫米到点（1英寸=72点，1英寸=25.4毫米）
        double widthPoints = request.getPaperWidth() * 72.0 / 25.4;
        double heightPoints = request.getPaperHeight() * 72.0 / 25.4;
        
        paper.setSize(widthPoints, heightPoints);
        paper.setImageableArea(0, 0, widthPoints, heightPoints);
        pageFormat.setPaper(paper);
        
        // 设置PDF打印器
        PDFPrintable pdfPrintable = new PDFPrintable(document, Scaling.ACTUAL_SIZE);
        printerJob.setPrintable(pdfPrintable, pageFormat);
        
        // 生成任务ID
        String jobId = UUID.randomUUID().toString();
        printerJob.setJobName("PrintTolls-" + jobId);
        
        // 执行打印
        printerJob.print(attributes);
        
        return jobId;
    }
} 